package xyz.labmem.app.main

import cn.hutool.core.collection.ConcurrentHashSet
import cn.hutool.core.util.RandomUtil
import javafx.animation.*
import javafx.application.Application
import javafx.application.HostServices
import javafx.event.ActionEvent
import javafx.scene.Cursor
import javafx.scene.Scene
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.layout.Background
import javafx.scene.layout.Pane
import javafx.stage.Stage
import javafx.stage.StageStyle
import javafx.util.Duration
import xyz.labmem.app.config.AppConfig
import xyz.labmem.app.config.AppConfig.loadingImage
import xyz.labmem.app.util.BackgroundMusic
import xyz.labmem.app.util.ScreenType
import xyz.labmem.lipx.core.util.ClientConfigDataUtil
import xyz.labmem.lipx.core.util.ServerConfigDataUtil
import xyz.labmem.util.getResourceFile
import xyz.labmem.util.viewRun
import java.util.*


/**
 * 初始化程序
 */
class MainApplication : Application() {

    private val rootPane = Pane()
    private val random: Random = Random()
    private var loop: Boolean = false
    private val peopleBox = ConcurrentHashSet<Int>()

    companion object {
        var hostServices: HostServices? = null
    }

    override fun start(primaryStage: Stage) {
        MainApplication.hostServices = hostServices
        rootPane.setPrefSize(ScreenType.sr.width, ScreenType.sr.height)
        val scene = Scene(rootPane)
        scene.fill = null
        scene.cursor = Cursor.cursor(getResourceFile("image/ui/mouse/m1.gif").url.toExternalForm())
        primaryStage.isAlwaysOnTop = true
        rootPane.background = Background.EMPTY
        primaryStage.title = AppConfig.appName
        primaryStage.icons.add(Image(getResourceFile(AppConfig.appIcon).stream))
        primaryStage.scene = scene
        primaryStage.initStyle(StageStyle.TRANSPARENT)
        BackgroundMusic.played()
        primaryStage.show()
        //logo登场
        val loading = ImageView(loadingImage["loading"]!!)
        loading.scaleX = 0.01
        loading.scaleY = 0.01
        loading.layoutXProperty().bind(rootPane.widthProperty().divide(2).subtract(loading.image.width / 2))
        loading.layoutYProperty().bind(rootPane.heightProperty().divide(2).subtract(loading.image.height / 2))
        rootPane.children.add(loading)
        val logoA = ScaleTransition(Duration.seconds(2.0), loading)
        logoA.byX = 1.0
        logoA.byY = 1.0
        logoA.interpolator = Interpolator.LINEAR // 动画插值器，使动画看起来更平滑
        logoA.play() // 开始播放动画
        logoA.setOnFinished {
            val timeline = Timeline(
                KeyFrame(Duration.millis(200.0), { _: ActionEvent? -> peopleLoading(false) }),
                KeyFrame(Duration.millis(300.0), { _: ActionEvent? -> peopleLoading(true) })
            )
            timeline.cycleCount = Timeline.INDEFINITE
            timeline.play()
            Thread {
                initConfig()
                viewRun {
                    rootPane.children.remove(loading)
                    rootPane.children.add(loading)
                    val logoB = Timeline(
                        KeyFrame(
                            Duration.seconds(2.0),
                            KeyValue(rootPane.layoutYProperty(), -rootPane.height),
                            KeyValue(rootPane.layoutXProperty(), rootPane.width)
                        ),
                        KeyFrame(
                            Duration.seconds(1.0),
                            KeyValue(rootPane.scaleYProperty(), 0),
                            KeyValue(rootPane.scaleXProperty(), 0)
                        ),
                        KeyFrame(
                            Duration.seconds(1.0),
                            KeyValue(rootPane.rotateProperty(), 900),
                        ),
                    )
                    logoB.play()
                    logoB.setOnFinished {
                        timeline.stop()
                        MainStage().run()
                        primaryStage.close()
                        //释放
                        for (k in 0..11) {
                            loadingImage.remove(k)
                        }
                        System.gc()
                    }
                }
            }.start()
        }
    }

    private fun peopleLoading(flip: Boolean) {
        if (peopleBox.size == 12) {
            peopleBox.clear()
            loop = !loop
        }
        val nextInt = if ((flip && !loop) || (!flip && loop)) {
            random(ArrayList(listOf(0, 2, 4, 6, 8, 10)))
        } else {
            random(ArrayList(listOf(1, 3, 5, 7, 9, 11)))
        }
        if (nextInt == -1)
            return

        val speed = random.nextDouble(1.0, 4.0)
        val crowd = loadingImage[nextInt]!!
        val imageView = ImageView(crowd)
        imageView.layoutY = rootPane.height - crowd.height + 20
        if (flip) {
            imageView.scaleX = -1.0
            imageView.layoutX = -crowd.width
        } else {
            imageView.layoutX = rootPane.width
        }
        val ud = Timeline(
            KeyFrame(
                Duration.millis(500.0),
                KeyValue(imageView.translateYProperty(), 60)
            ), // 向下移动
            KeyFrame(
                Duration.seconds(1.0),
                KeyValue(imageView.translateYProperty(), 0)
            ), // 回到原位
        )
        ud.cycleCount = Timeline.INDEFINITE;
        ud.play()

        val lr = Timeline(
            KeyFrame(
                Duration.seconds(speed),
                { _: ActionEvent? ->
                    ud.stop()
                    rootPane.children.remove(imageView)
                },
                KeyValue(
                    imageView.translateXProperty(),
                    if (flip) rootPane.width + crowd.width else -(crowd.width + rootPane.width + crowd.width)
                )
            ), // 左右移动
        )
        lr.play()
        rootPane.children.add(imageView)
    }

    private fun random(set: ArrayList<Int>): Int {
        return if (set.isEmpty()) {
            -1
        } else {
            val nextInt = RandomUtil.randomEle(set)
            if (peopleBox.contains(nextInt)) {
                set.remove(nextInt)
                return random(set)
            } else {
                peopleBox.add(nextInt)
                return nextInt
            }
        }
    }

    private fun initConfig() {
        //加载资源
        AppConfig.initConfig()
        BackgroundMusic.init()
        //配置加载
        setUserAgentStylesheet("/css/primer-dark.css")
        ClientConfigDataUtil.init()
        ServerConfigDataUtil.init()
        Thread.sleep(1000)
    }
}